/****************************************************************************
* copyright            : (C) 2009 William Viana Soares <vianasw@gmail.com>  *
*****************************************************************************/

/****************************************************************************
*                                                                           *
*   This program is free software; you can redistribute it and/or modify    *
*   it under the terms of the GNU General Public License as published by    *
*   the Free Software Foundation; either version 2 of the License, or       *
*   (at your option) any later version.                                     *
*                                                                           *
*****************************************************************************/

#include "querymaker.h"

#include <boost/asio.hpp>

namespace ConciseQSR
{
QueryMaker::QueryMaker( boost::asio::io_service &io_service, string host, string port )
    : m_host( host )
    , m_port( port )
    , m_response( new boost::asio::streambuf )
    , m_request( new boost::asio::streambuf )
    , m_socket( new tcp::socket( io_service ) )
{
    try
    {           
        tcp::resolver            resolver( io_service );
        tcp::resolver::query     query( tcp::v4(), m_host, m_port );
        tcp::resolver::iterator  iterator = resolver.resolve( query );
        
        m_socket->connect( *iterator );
        
        //read sparq wellcome message
        boost::asio::read_until( *m_socket, *m_response, "sparq> " );
                
    }
    catch( exception &e )
    {
        cerr << "Exception: " << e.what() << endl;
        throw e;
    }
    
}


QueryMaker::~QueryMaker()
{
    makeQuery( "quit\n" );
    m_socket->close();
}

string QueryMaker::aClosure( const string &constraints ) const
{
    string command = "constraint-reasoning dcc a-closure " + constraints + "\n";
    return makeQuery( command );
}

string QueryMaker::computeRelation( string op, const string &baseRelation ) const
{
    string command = "compute-relation dcc " +  op + " " + baseRelation + "\n";
    return makeQuery( command );
}

string QueryMaker::makeQuery( const string &command ) const
{
    //consume garbage from the buffer
    m_response->consume( m_response->size() );
    
    ostream requestStream( &( *m_request ) );
    istream responseStream( &( *m_response ) );
    
    string returnString;
    string aux;
    
    requestStream << command;
    boost::asio::write( *m_socket, *m_request );

    boost::system::error_code error;
    boost::asio::read_until( *m_socket, *m_response, "sparq> ", error );

    while( getline( responseStream, aux ) && aux != "sparq> " )
    {
        returnString += aux;
    }
    if( command == "quit\n" && error != boost::asio::error::eof )
        throw boost::system::system_error( error );
    return returnString;
}

string QueryMaker::qualifyPoints( const string &points ) const
{
    string command = "qualify dcc first2all " + points + "\n";
    return makeQuery( command );
}

string QueryMaker::qualifyPointsAll( const string &points ) const
{
    string command = "qualify dcc all " + points + "\n";
    return makeQuery( command );
}

} //namespace ConciseQSR